// 优化版本，增加了请求重试和取消功能
import axios, {
  InternalAxiosRequestConfig,
  AxiosResponse,
  CancelToken,
} from "axios";
import { useUserStoreHook } from "@/store/modules/user";
import { ResultEnum } from "@/enums/ResultEnum";
import { TOKEN_KEY } from "@/enums/CacheEnum";
import qs from "qs";
import { ElMessage, ElNotification } from "element-plus";

// 创建 axios 实例
const service = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API,
  timeout: 50000,
  headers: { "Content-Type": "application/json;charset=utf-8" },
  paramsSerializer: (params) => {
    return qs.stringify(params); // 将参数序列化为查询字符串
  },
});

const pendingRequests = new Map(); // 用于存储挂起的请求

// 请求拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const accessToken = localStorage.getItem(TOKEN_KEY);
    if (accessToken) {
      config.headers.Authorization = accessToken; // 将 token 添加到请求头
    }

    // 请求取消处理，防止重复请求
    const source = CancelToken.source();
    config.cancelToken = source.token;
    pendingRequests.set(config.url, source); // 将请求添加到挂起列表中

    return config; // 返回配置后发起请求
  },
  (error: any) => {
    return Promise.reject(error); // 请求错误处理
  }
);

// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse) => {
    pendingRequests.delete(response.config.url); // 响应成功后移除挂起的请求

    // 检查是否是二进制响应
    if (
      response.config.responseType === "blob" ||
      response.config.responseType === "arraybuffer"
    ) {
      return response;
    }

    const { code, data, msg, success } = response.data;
    if (code === ResultEnum.SUCCESS || success) {
      return data; // 请求成功，返回数据
    }

    ElMessage.error(msg || "系统出错");
    return Promise.reject(new Error(msg || "Error")); // 请求失败处理
  },
  (error: any) => {
    pendingRequests.delete(error.config.url); // 响应失败时从挂起列表中移除
    handleError(error); // 调用统一的错误处理函数
    return Promise.reject(error.message);
  }
);

// 统一的错误处理函数
function handleError(error) {
  if (!error.response) {
    ElMessage.error("网络错误"); // 网络错误提示
    return;
  }

  const { code, msg } = error.response.data || {};
  switch (code) {
    case ResultEnum.TOKEN_INVALID:
      ElNotification({
        title: "提示",
        message: "您的会话已过期，请重新登录",
        type: "info",
      });
      useUserStoreHook()
        .resetToken()
        .then(() => {
          location.reload(); // 重置 token 并重新加载页面
        });
      break;
    default:
      ElMessage.error(msg || "系统出错"); // 其他错误提示
  }
}

// 请求重试机制
function retryRequest(config, retries = 3) {
  return new Promise((resolve, reject) => {
    const attemptRequest = (retryCount) => {
      service
        .request(config) // 发送请求
        .then((res) => {
          resolve(res); // 成功返回结果
        })
        .catch((err) => {
          if (retryCount > 0) {
            console.log(`请求失败，正在重试... 剩余次数：${retryCount}`);
            attemptRequest(retryCount - 1); // 递归重试
          } else {
            reject(err); // 重试次数用完，抛出错误
          }
        });
    };
    attemptRequest(retries); // 发起请求并处理重试
  });
}

// 取消所有挂起请求
function cancelAllRequests() {
  pendingRequests.forEach((source) => {
    source.cancel("请求已取消"); // 取消请求
  });
  pendingRequests.clear(); // 清空挂起请求
}

// 导出封装好的 axios 实例
export default {
  service, // axios 实例
  retryRequest, // 重试请求功能
  cancelAllRequests, // 取消请求功能
};
// 使用方法：
// 在组件或其他文件中
// import { service } from '@/utils/request'; // 导入 axios 实例
//   const data = await service.get('/api/data'); // 使用 service 发起 GET 请求
